package com.emmmya.ocs.config.redis;

import com.emmmya.ocs.common.utils.SerializeUtil;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * @author: laijieguan
 * @date: 2020/07/13
 * @description: redis配置
 */
@Configuration
@EnableCaching
public class RedisConfig {

    /**
     * redis地址
     */
    @Value("${spring.redis.host}")
    private String host;

    /**
     * redis端口号
     */
    @Value("${spring.redis.port}")
    private Integer port;

    /**
     * redis密码
     */
    @Value("${spring.redis.password}")
    private String password;

    /**
     * JedisPoolConfig 连接池
     * @return
     */
//    @Bean
//    public JedisPoolConfig jedisPoolConfig(){
//        //GenericObjectPoolConfig jedisPoolConfig=new JedisPoolConfig();
//        JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();
//        //最大空闲数
//        jedisPoolConfig.setMaxIdle(300);
//        //连接池的最大数据库连接数
//        jedisPoolConfig.setMaxTotal(1000);
//        //最大建立连接等待时间
//        jedisPoolConfig.setMaxWaitMillis(1000);
//        //逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
//        jedisPoolConfig.setMinEvictableIdleTimeMillis(300000);
//        //每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
//        jedisPoolConfig.setNumTestsPerEvictionRun(10);
//        //逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
//        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(30000);
//        //是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
//        jedisPoolConfig.setTestOnBorrow(true);
//        //在空闲时检查有效性, 默认false
//        jedisPoolConfig.setTestWhileIdle(true);
//        return jedisPoolConfig;
//    }
    @Bean
    public GenericObjectPoolConfig getPoolConfig(){
        // 配置redis连接池
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxTotal(1000);
        poolConfig.setMaxIdle(300);
        poolConfig.setMinIdle(300);
        poolConfig.setMaxWaitMillis(1000);
        return poolConfig;
    }
    //系统通用的redis管理器
    @Bean(name = "sscRedisTemplate")
    public RedisTemplate getRedisTemplate(){
        return getStringRedisTemplate(0);
    }

    //系统缓存redis
    @Bean(name = "cacheRedisTemplate")
    public RedisTemplate getCacheRedisTemplate(){
        return getStringRedisTemplate(3);
    }



    //shiro的redis管理器
    @Bean(name = "shiroRedisTemplate")
    public RedisTemplate getShiroRedisTemplate(){
        // 构建工厂对象
        return getStringRedisTemplate(1);
    }

    private RedisTemplate getStringRedisTemplate(int database) {
        // 构建工厂对象
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName(host);
        configuration.setPort(port);
        configuration.setPassword(RedisPassword.of(password));
        LettucePoolingClientConfiguration clientConfiguration = LettucePoolingClientConfiguration.builder()
                .commandTimeout(Duration.ofSeconds(30)).poolConfig(getPoolConfig()).build();
        LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration, clientConfiguration);
        // 设置使用的redis数据库
        factory.setDatabase(database);
        // 重新初始化工厂
        factory.afterPropertiesSet();

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        if(database == 0){
            // 设置 key 的序列化的方式
            template.setKeySerializer(RedisSerializer.string());
            // 设置 value 的序列化的方式
            template.setValueSerializer(RedisSerializer.json());
            // 设置 hash 的 key 的序列化的方式
            template.setHashKeySerializer(RedisSerializer.string());
            // 设置 hash 的 value 的序列化的方式
            template.setHashValueSerializer(RedisSerializer.json());
        }else if(database == 1){
            SerializeUtil serializeUtils = new SerializeUtil();
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            // 设置 key 的序列化的方式
            template.setKeySerializer(stringRedisSerializer);
            // 设置 value 的序列化的方式
            template.setValueSerializer(serializeUtils);
            // 设置 hash 的 key 的序列化的方式
            template.setHashKeySerializer(stringRedisSerializer);
            // 设置 hash 的 value 的序列化的方式
            template.setHashValueSerializer(serializeUtils);
        }else {
            SerializeUtil serializeUtils = new SerializeUtil();
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            // 设置 key 的序列化的方式
            template.setKeySerializer(stringRedisSerializer);
            // 设置 value 的序列化的方式
            template.setValueSerializer(serializeUtils);
            // 设置 hash 的 key 的序列化的方式
            template.setHashKeySerializer(stringRedisSerializer);
            // 设置 hash 的 value 的序列化的方式
            template.setHashValueSerializer(serializeUtils);
        }
        return template;
    }


    /**
     * shiro redis缓存使用的模板
     * 实例化 RedisTemplate 对象
     * @return
     */
    //@Bean("shiroRedisTemplate")
    public RedisTemplate shiroRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        //SerializeUtils serializeUtils = new SerializeUtils();
        //StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();


        //RedisTemplate redisTemplate = new RedisTemplate();
        //redisTemplate.setKeySerializer(stringRedisSerializer);
        //redisTemplate.setHashKeySerializer(stringRedisSerializer);
        //redisTemplate.setHashValueSerializer(serializeUtils);
        //redisTemplate.setValueSerializer(serializeUtils);
        //开启事务
        //stringRedisTemplate.setEnableTransactionSupport(true);
        //redisTemplate.setConnectionFactory(redisConnectionFactory);
        //return redisTemplate;
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // 设置 key 的序列化的方式
        template.setKeySerializer(RedisSerializer.string());
        // 设置 value 的序列化的方式
        template.setValueSerializer(RedisSerializer.json());
        // 设置 hash 的 key 的序列化的方式
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置 hash 的 value 的序列化的方式
        template.setHashValueSerializer(RedisSerializer.json());

        template.afterPropertiesSet();
        return template;
    }

    /**
     * 缓存管理器
     *
     * @param lettuceConnectionFactory
     * @return
     */
//    @Bean
//    public CacheManager cacheManager(RedisConnectionFactory lettuceConnectionFactory) {
//        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig();
//        // 设置缓存管理器管理的缓存的默认过期时间
//        defaultCacheConfig = defaultCacheConfig.entryTtl(Duration.ofSeconds(1800000))
//                // 设置 key为string序列化
//                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
//                // 设置value为json序列化
//                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
//                // 不缓存空值
//                .disableCachingNullValues();
//
//        Set<String> cacheNames = new HashSet<>();
//        cacheNames.add("Harin");
//
//        // 对每个缓存空间应用不同的配置
//        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
//        configMap.put("Harin", defaultCacheConfig.entryTtl(Duration.ofSeconds(1800000)));
//
//        RedisCacheManager cacheManager = RedisCacheManager.builder(lettuceConnectionFactory)
//                .cacheDefaults(defaultCacheConfig)
//                .initialCacheNames(cacheNames)
//                .withInitialCacheConfigurations(configMap)
//                .build();
//        return cacheManager;
//    }

}
